#ifndef __DICT_VECTOR_HH__
#define __DICT_VECTOR_HH__

#include <sstream>
#include <vector>
#include <map>
using namespace std;

#include <misc/error.h>

template <typename K, typename V>
class DictVector
{
public:
  size_t size() const;
  bool has_key(const K& key) const;
  vector<K> keys() const;
  vector<V> get_values() const;
  const V& get(const K& key) const;
  V* get_ptr(const K& key);
  void set(const K& key, const V& value);	     
  void remove(const K& key);

  bool find(const K& key, size_t* key_index) const;

  bool push_back(const K&, const V& v);
  const K& key_at(size_t key_index) const;
  const V& get_at(size_t key_index) const;
  V* get_ptr_at(size_t key_index);
  void set_at(size_t key_index, const V& v);
  void remove_at(size_t key_index);

private:

  vector<pair<K, V> > values;
  typedef map<K, size_t> value_indexes_t;
  value_indexes_t value_indexes;
};

template <class K, class V>
inline
size_t DictVector<K, V>::size() const {
  return values.size(); 
}

template <class K, class V>
inline
bool DictVector<K, V>::has_key(const K& key) const 
{ 
  return value_indexes.find(key) != value_indexes.end();
}

template <class K, class V>
inline
vector<K> DictVector<K, V>::keys() const 
{
  vector<K> ret;
  for (int i = 0; i < values.size(); i++) {
    ret.push_back(values[i].first);
  }
  return ret;
}

template <class K, class V>
inline
vector<V> DictVector<K, V>::get_values() const 
{
  vector<V> ret;
  for (int i = 0; i < values.size(); i++) {
    ret.push_back(values[i].second);
  }
  return ret;
}

template <class K, class V>
inline
const V& DictVector<K, V>::get(const K& key) const 
{ 
  typename value_indexes_t::const_iterator it = value_indexes.find(key);
  if (it == value_indexes.end()) {
    ostringstream msg;
    msg << "DictVector<K,V>::get: no such key: " << key;
    throw Error(__FILE__, __LINE__, msg.str());
  }
  return values[(*it).second].second;
}

template <class K, class V>
inline
V* DictVector<K, V>::get_ptr(const K& key)
{ 
  typename value_indexes_t::iterator it = value_indexes.find(key);
  if (it == value_indexes.end()) {
    throw Error(__FILE__, __LINE__, "DictVector<K,V>::get_ptr: no such key");
  }
  return &values[(*it).second].second;
}

template <class K, class V>
inline
bool DictVector<K, V>::push_back(const K& key, const V& value)
{
  if (has_key(key)) {
    return false;
  }
  this->set(key, value);
  return true;
}

template <class K, class V>
inline
void DictVector<K, V>::set(const K& key, const V& value) 
{
  typename value_indexes_t::iterator it = value_indexes.find(key);    
  if (it == value_indexes.end()) {
    values.push_back(make_pair(key, value));
    value_indexes[key] = values.size() - 1;
  } else {
    values[(*it).second].second = value;
  }
}

template <class K, class V>
inline
void DictVector<K, V>::set_at(size_t key_index, const V& value)
{
  values[key_index].second = value;
}

template <class K, class V>
inline
void DictVector<K, V>::remove(const K& key) 
{
  size_t key_index = 0;
  if (find(key, &key_index) == false) {
    return;
  }
  values.erase(values.begin() + key_index, values.begin() + key_index + 1);
  value_indexes.erase(key);
  int c = 0;
  for (typename value_indexes_t::iterator it = value_indexes.begin();
       it != value_indexes.end();
       ++it, c++) {
    (*it).second = c;
  }
}

template <class K, class V>
inline
bool DictVector<K, V>::find(const K& key, size_t* key_index) const
{
  typename value_indexes_t::const_iterator it = value_indexes.find(key);
  if (it == value_indexes.end()) {
    return false;
  }
  if (key_index) *key_index = (*it).second;
  return true;
}

template <class K, class V>
inline
const K& DictVector<K, V>::key_at(size_t key_index) const
{
  return values[key_index].first;
}

template <class K, class V>
inline
const V& DictVector<K, V>::get_at(size_t key_index) const
{
  return values[key_index].second;
}

#if 0
const K& key_at(size_t index) const {...}
bool find_at(const K& key, size_t* key_index) const {...}
const V& get_at(size_t index) const {...}
V* get_ptr_at(size_t index) { ... }
void remove_at(size_t index) { ....}

private:

  vector<pair<K, V> > values;
  typedef map<K, size_t> value_indexe_t;
  value_indexes_t value_indexes;
};
#endif

#endif
